Rework the code which emits ::grab-notify signals to ensure that we emit
authorMatthias Clasen <mclasen@redhat.com>
Thu, 6 Apr 2006 01:58:38 +0000 (01:58 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Thu, 6 Apr 2006 01:58:38 +0000 (01:58 +0000)
2006-04-05  Matthias Clasen  <mclasen@redhat.com>

* gtk/gtkmain.c (gtk_grab_add, gtk_grab_remove, gtk_grab_notify)
(gtk_grab_notify_foreach): Rework the code which emits ::grab-notify
signals to ensure that we emit enough signals. Also optimize the
code to not do unnecessary tree walking.

* gtk/gtkwidget.c (gtk_widget_class_init): Document ::grab-notify.

ChangeLog
ChangeLog.pre-2-10
gtk/gtkmain.c
gtk/gtkwidget.c

index 651a9defeb01f93a78f2b7553270d98f6fd1ec9c..816dc746c7c60254816799a2be95f2b3c9b06b86 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2006-04-05  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtkmain.c (gtk_grab_add, gtk_grab_remove, gtk_grab_notify) 
+       (gtk_grab_notify_foreach): Rework the code which emits ::grab-notify
+       signals to ensure that we emit enough signals. Also optimize the
+       code to not do unnecessary tree walking.
+
+       * gtk/gtkwidget.c (gtk_widget_class_init): Document ::grab-notify.
+
 2006-04-05  Paolo Borelli  <pborelli@katamail.com>
 
        * gtk/gtktextiter.c (gtk_text_iter_ends_line): handle the case of \r
index 651a9defeb01f93a78f2b7553270d98f6fd1ec9c..816dc746c7c60254816799a2be95f2b3c9b06b86 100644 (file)
@@ -1,3 +1,12 @@
+2006-04-05  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtkmain.c (gtk_grab_add, gtk_grab_remove, gtk_grab_notify) 
+       (gtk_grab_notify_foreach): Rework the code which emits ::grab-notify
+       signals to ensure that we emit enough signals. Also optimize the
+       code to not do unnecessary tree walking.
+
+       * gtk/gtkwidget.c (gtk_widget_class_init): Document ::grab-notify.
+
 2006-04-05  Paolo Borelli  <pborelli@katamail.com>
 
        * gtk/gtktextiter.c (gtk_text_iter_ends_line): handle the case of \r
index ab4684db6c42238a2148fc0506cc6d2b7c5b68d1..da96941a0258af06b30e460ec83b296154942708 100644 (file)
@@ -1395,6 +1395,7 @@ gtk_main_do_event (GdkEvent *event)
     case GDK_VISIBILITY_NOTIFY:
     case GDK_WINDOW_STATE:
     case GDK_GRAB_BROKEN:
+    case GDK_DAMAGE:
       gtk_widget_event (event_widget, event);
       break;
 
@@ -1496,61 +1497,57 @@ typedef struct
 {
   GtkWidget *old_grab_widget;
   GtkWidget *new_grab_widget;
+  gboolean   was_grabbed;
+  gboolean   is_grabbed;
 } GrabNotifyInfo;
 
-static gboolean
-check_is_grabbed (GtkWidget *widget,
-                 GtkWidget *grab_widget)
-{
-  if (grab_widget)
-    return !(widget == grab_widget || gtk_widget_is_ancestor (widget, grab_widget));
-  else
-    return FALSE;
-}
-
 static void
 gtk_grab_notify_foreach (GtkWidget *child,
                         gpointer   data)
                         
 {
   GrabNotifyInfo *info = data;
-  gboolean was_grabbed = check_is_grabbed (child, info->old_grab_widget);
-  gboolean is_grabbed = check_is_grabbed (child, info->new_grab_widget);
+  gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
 
-  if (was_grabbed != is_grabbed)
-    {
-      g_object_ref (child);
+  was_grabbed = info->was_grabbed;
+  is_grabbed = info->is_grabbed;
 
-      _gtk_widget_grab_notify (child, was_grabbed);
-      
-      if (GTK_IS_CONTAINER (child))
-       gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
+  info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
+  info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
+
+  was_shadowed = info->old_grab_widget && !info->was_grabbed;
+  is_shadowed = info->new_grab_widget && !info->is_grabbed;
+
+  g_object_ref (child);
+  
+  if (was_shadowed != is_shadowed)
+    _gtk_widget_grab_notify (child, was_shadowed);
+  
+  if (GTK_IS_CONTAINER (child))
+    gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
       
-      g_object_unref (child);
-    }
+  g_object_unref (child);
+  
+  info->was_grabbed = was_grabbed;
+  info->is_grabbed = is_grabbed;
 }
 
 static void
 gtk_grab_notify (GtkWindowGroup *group,
-                GtkWidget      *grab_widget,
-                gboolean        was_grabbed)
+                GtkWidget      *old_grab_widget,
+                GtkWidget      *new_grab_widget)
 {
   GList *toplevels;
   GrabNotifyInfo info;
 
-  if (was_grabbed)
-    {
-      info.old_grab_widget = grab_widget;
-      info.new_grab_widget = group->grabs ? group->grabs->data : NULL;
-    }
-  else
-    {
-      info.old_grab_widget = (group->grabs && group->grabs->next) ? group->grabs->next->data : NULL;
-      info.new_grab_widget = grab_widget;
-    }
+  if (old_grab_widget == new_grab_widget)
+    return;
+
+  info.old_grab_widget = old_grab_widget;
+  info.new_grab_widget = new_grab_widget;
 
   g_object_ref (group);
-  g_object_ref (grab_widget);
 
   toplevels = gtk_window_list_toplevels ();
   g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
@@ -1560,19 +1557,23 @@ gtk_grab_notify (GtkWindowGroup *group,
       GtkWindow *toplevel = toplevels->data;
       toplevels = g_list_delete_link (toplevels, toplevels);
 
+      info.was_grabbed = FALSE;
+      info.is_grabbed = FALSE;
+
       if (group == gtk_window_get_group (toplevel))
-       gtk_container_foreach (GTK_CONTAINER (toplevel), gtk_grab_notify_foreach, &info);
+       gtk_container_foreach (GTK_CONTAINER (toplevel), 
+                              gtk_grab_notify_foreach, &info);
       g_object_unref (toplevel);
     }
 
   g_object_unref (group);
-  g_object_unref (grab_widget);
 }
 
 void
 gtk_grab_add (GtkWidget *widget)
 {
   GtkWindowGroup *group;
+  GtkWidget *old_grab_widget;
   
   g_return_if_fail (widget != NULL);
   
@@ -1582,10 +1583,15 @@ gtk_grab_add (GtkWidget *widget)
       
       group = gtk_main_get_window_group (widget);
 
+      if (group->grabs)
+       old_grab_widget = (GtkWidget *)group->grabs->data;
+      else
+       old_grab_widget = NULL;
+
       g_object_ref (widget);
       group->grabs = g_slist_prepend (group->grabs, widget);
 
-      gtk_grab_notify (group, widget, FALSE);
+      gtk_grab_notify (group, old_grab_widget, widget);
     }
 }
 
@@ -1605,6 +1611,7 @@ void
 gtk_grab_remove (GtkWidget *widget)
 {
   GtkWindowGroup *group;
+  GtkWidget *new_grab_widget;
   
   g_return_if_fail (widget != NULL);
   
@@ -1615,9 +1622,14 @@ gtk_grab_remove (GtkWidget *widget)
       group = gtk_main_get_window_group (widget);
       group->grabs = g_slist_remove (group->grabs, widget);
       
-      g_object_unref (widget);
+      if (group->grabs)
+       new_grab_widget = (GtkWidget *)group->grabs->data;
+      else
+       new_grab_widget = NULL;
 
-      gtk_grab_notify (group, widget, TRUE);
+      gtk_grab_notify (group, widget, new_grab_widget);
+      
+      g_object_unref (widget);
     }
 }
 
index d7687ddef430be5b2b907656fbf1a28e7758ea3c..3eb16d2aee2663f4aa8e447e55431393ac2a0757 100644 (file)
@@ -121,6 +121,7 @@ enum {
   SCREEN_CHANGED,
   CAN_ACTIVATE_ACCEL,
   GRAB_BROKEN,
+  DAMAGE_EVENT,
   LAST_SIGNAL
 };
 
@@ -402,6 +403,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
   klass->screen_changed = NULL;
   klass->can_activate_accel = gtk_widget_real_can_activate_accel;
   klass->grab_broken_event = NULL;
+  klass->damage_event = NULL;
 
   klass->show_help = gtk_widget_real_show_help;
   
@@ -664,6 +666,22 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                  _gtk_marshal_VOID__ENUM,
                  G_TYPE_NONE, 1,
                  GTK_TYPE_TEXT_DIRECTION);
+
+  /**
+   * GtkWidget::grab-notify:
+   * @widget: the object which received the signal
+   * @was_grabbed: %FALSE if the widget becomes shadowed, %TRUE
+   *               if it becomes unshadowed
+   *
+   * The ::grab-notify signal is emitted when a widget becomes
+   * shadowed by a GTK+ grab (not a pointer or keyboard grab) on 
+   * another widget, or when it becomes unshadowed due to a grab 
+   * being removed.
+   * 
+   * A widget is shadowed by a gtk_grab_add() when the topmost 
+   * grab widget in the grab stack of its window group is not 
+   * its ancestor.
+   */
   widget_signals[GRAB_NOTIFY] =
     g_signal_new (I_("grab_notify"),
                  G_TYPE_FROM_CLASS (gobject_class),
@@ -1362,6 +1380,29 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                  _gtk_marshal_BOOLEAN__BOXED,
                  G_TYPE_BOOLEAN, 1,
                  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+  /**
+   * GtkWidget::damage-event:
+   * @widget: the object which received the signal
+   * @event: the #GdkEventExpose event
+   *
+   * Emitted when a redirected window belonging to @widget gets drawn into.
+   * The region/area members of the event shows what area of the redirected
+   * drawable was drawn into.
+   *
+   * Returns: %TRUE to stop other handlers from being invoked for the event. 
+   *   %FALSE to propagate the event further.
+   *
+   * Since: 2.10
+   */
+  widget_signals[DAMAGE_EVENT] =
+    g_signal_new ("damage_event",
+                 G_TYPE_FROM_CLASS (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GtkWidgetClass, damage_event),
+                 _gtk_boolean_handled_accumulator, NULL,
+                 _gtk_marshal_BOOLEAN__BOXED,
+                 G_TYPE_BOOLEAN, 1,
+                 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 /**
  * GtkWidget::popup-menu
  * @widget: the object which received the signal
@@ -3773,6 +3814,9 @@ gtk_widget_event_internal (GtkWidget *widget,
        case GDK_GRAB_BROKEN:
          signal_num = GRAB_BROKEN;
          break;
+       case GDK_DAMAGE:
+         signal_num = DAMAGE_EVENT;
+         break;
        default:
          g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
          signal_num = -1;